package org.comple.erp.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.UUID;

@Slf4j
public class JwtUtil {
    // 密钥
    public static final String SECRET = "ff82854752c9d95afb57290fd7b9025af9ff3ee416c889c3870beacc290ca249";

    //间隔时间 单位分钟
    public static final Integer INTERVAL = 300;

    //生成token
    public static String createToken(String staffId, String companyCode, String name) {
        Date latDate = new Date();
        Date expDate = new Date(latDate.getTime() + INTERVAL * 60 * 1000);

        return JWT.create()
                .withJWTId(UUID.randomUUID().toString())
                .withIssuedAt(latDate) //jwt生成的时间
                .withExpiresAt(expDate)//jwt过期的时间
                .withClaim("userId", staffId)//向jwt中添加数据，可以添加多个，可被调用多次
                .withClaim("companyCode", companyCode) // 公司编码
                .withClaim("name", name)
                .sign(Algorithm.HMAC256(SECRET));//添加签名
    }

    //根据token验证是否有效
    public static DecodedJWT verifyToken(String token) {
        try {
            DecodedJWT decodedJwt = JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
            Date expDate = decodedJwt.getExpiresAt();
            log.info("距离过期时间还剩" + (expDate.getTime() - System.currentTimeMillis()) / 1000 + "秒");
            return decodedJwt;
        } catch (TokenExpiredException e) {
            // 捕获：令牌过期
            // 建议抛出一个自定义异常，例如 TokenValidationException.expired(e.getMessage())
            throw new RuntimeException("JWT 令牌已过期: " + e.getMessage());
        } catch (SignatureVerificationException e) {
            // 捕获：签名验证失败（密钥错误或被篡改）
            throw new RuntimeException("JWT 签名验证失败: " + e.getMessage());
        } catch (AlgorithmMismatchException e) {
            // 捕获：算法不匹配
            throw new RuntimeException("JWT 算法不匹配: " + e.getMessage());
        } catch (InvalidClaimException e) {
            // 捕获：Claim 验证失败（例如，Issuer, Audience 错误）
            throw new RuntimeException("JWT Claim 验证失败: " + e.getMessage());
        } catch (Exception e) {
            // 捕获其他所有 JWT 相关的验证异常 (JWTVerificationException 的其他子类)
            // 或其他意外的 RuntimeException。
            // 此时应该记录日志，并抛出一个通用的 Token 验证失败异常。
            throw new RuntimeException("JWT 验证失败，未知错误: " + e.getMessage(), e);
        }
    }

    //读取jwt中存储数据
    public static String getUserId(String token) {
        return verifyToken(token).getClaim("userId").asString();
    }

    public static String getCompanyCode(String token) {
        return verifyToken(token).getClaim("companyCode").asString();
    }

    public static String getName(String token) {
        return verifyToken(token).getClaim("name").asString();
    }

    //获取到期时间
    public static Date getExpires(String token) {
        return verifyToken(token).getExpiresAt();
    }
}
